package com.itheima.controller;

import com.itheima.po.Node;
import com.itheima.po.NodeAndUser;
import com.itheima.po.User;
import com.itheima.service.NodeService;
import com.itheima.service.UserService;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/node")
public class NodeConntroller {

    @Autowired
    private UserService userService;
    @Autowired
    private NodeService nodeService;

    //笔记上传
    @RequestMapping("/upload")
    public String handleFormUpload(@RequestParam(value="name") String nodename,
                                   @RequestParam(value="language")String language,
                                   @RequestParam(value="class")String nodeClass,
                                   @RequestParam(value="file") List<MultipartFile> uploadfile,
                                   @CookieValue(value="username",required = false) String username,
                                   HttpServletRequest request) {
        //判断上传的文件是否存在
        if(!uploadfile.isEmpty() && uploadfile.size()>0) {
            //获取上传用户的用户id
            User user = userService.findUserByUsername(username);
            //获取当前年月日
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String dateNow = sdf.format(new Date());
            System.out.println("当前上传笔记时间：" + dateNow);
            for (MultipartFile file : uploadfile) {
                //获取文件的原始名称
                //String originalFilename = file.getOriginalFilename();
                //设置文件的保存目录地址 upload/用户id/笔记类别/笔记语言
                String dirPath = request.getServletContext().getRealPath("/upload/" + user.getUser_id() + "/"  + nodeClass + "/" + language + "/");
                File filePath = new File(dirPath);
                //若保存文件的地址不存在，则创建目录
                if(!filePath.exists()) {
                    filePath.mkdirs();
                }
                //使用UUID重新命名上传的文件名称(笔记名_uuid_笔记文件名称)
                //String newFilename = name + "_" + UUID.randomUUID() + "_" + originalFilename;
                //定义上传的文件名为：笔记名_笔记原名称
                String newFilename = nodename + ".md";
                //使用MultipartFile接口的方法完成文件上传到指定位置
                try {
                    file.transferTo(new File(dirPath + "\\" +  newFilename));
                    System.out.println("上传文件所在位置:"+dirPath);
                    System.out.println("上传文件的文件名:"+newFilename);
                } catch (Exception e) {
                    e.printStackTrace();
                    return "error";
                }
            }
            //文件上传成功，向数据库中存入笔记相关信息
            //1.创建笔记对象
            Node node = new Node();
            node.setNodename(nodename);
            node.setClass_name(nodeClass);
            node.setLanguage(language);
            node.setUser_id(user.getUser_id());
            node.setTime(dateNow);
            //2.将笔记名，用户id，笔记语言，笔记类型，笔记地址存入数据库
            nodeService.createNode(node);
            return "upload_page";
        }else {
            return "error";
        }
    }


    //搜索笔记请求处理
    @RequestMapping("/select")
    @ResponseBody
    public List<NodeAndUser> select(@RequestBody NodeAndUser nodeAndUser){
        System.out.println("开始搜索!");
        List<NodeAndUser> nodes =  nodeService.findNode(nodeAndUser);
        System.out.println(nodes);
        return nodes;
    }

    @RequestMapping("/selectMyNode")
    @ResponseBody
    public List<NodeAndUser> selectMyNode(@RequestBody NodeAndUser nodeAndUser){
        System.out.println("开始搜索!");
        List<NodeAndUser> nodes =  nodeService.findNodeByUsername(nodeAndUser);
        System.out.println(nodes);
        return nodes;
    }
    //笔记下载
    @RequestMapping("/downloadTry")
    public ResponseEntity<byte[]> downloadTry(@RequestParam(value="nodename")String nodename,
                                              @RequestParam(value="class_name")String class_name,
                                              @RequestParam(value="language")String language,
                                              @RequestParam(value="username")String username,
                                              HttpServletRequest request) throws Exception{
        NodeAndUser nodeAndUser = new NodeAndUser();
        nodeAndUser.setNodename(nodename);
        nodeAndUser.setClass_name(class_name);
        nodeAndUser.setLanguage(language);
        nodeAndUser.setUsername(username);
        System.out.println("接收到要下载的笔记信息："+nodeAndUser);
        //获取userId
        User author = userService.findUserByUsername(nodeAndUser.getUsername());
        System.out.println("该笔记的作者id:"+author.getUser_id());
        //指定要下载的文件的所在路径:/upload/作者id/笔记类型/笔记语言
        String path = request.getServletContext().getRealPath("/upload/" + author.getUser_id() + "/" + nodeAndUser.getClass_name() + "/" + nodeAndUser.getLanguage() + "/");
        System.out.println("下载路径："+path);
        String nodeName = nodeAndUser.getNodename() + ".md";
        System.out.println("文件名："+nodeName);
        //获取nodeId
        NodeAndUser node = nodeService.fingNodeByNodename(nodeAndUser);
        System.out.println("该笔记的笔记id:"+node.getNode_id());
        //下载的note人气+1
        nodeService.NodePopularityAdd1(node.getNode_id());
        //创建文件对象
        File file = new File(path+File.separator+nodeName);
        //对文件名编码，防止中文乱码
        String filename = this.getFilename(request,nodeName);
        //设置响应头
        HttpHeaders headers = new HttpHeaders();
        //通知浏览器以下载的形式打开文件
        headers.setContentDispositionFormData("attachment", filename);
        //定义以流的形式下载返回文件数据
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //使用springMVC框架的ResponseEntity对象封装返回下载的文件数据
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
    }
    //根据浏览器的不同进行编码设置，返回编码后的文件名
    private String getFilename(HttpServletRequest request, String filename)throws Exception{
        //IE不同版本User-Agent出现的关键词
        String[] IEBrowserKeyWords = {"MSIE","Trident","Edge"};
        //获取请求头代理信息
        String userAgent = request.getHeader("User-Agent");
        for(String keyWord : IEBrowserKeyWords) {
            if(userAgent.contains(keyWord)) {
                //IE内核浏览器，统一为UTF-8编码
                return URLEncoder.encode(filename,"UTF-8");
            }
        }
        //火狐等其他浏览器统一为ISO-8859-1编码显示
        return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
    }

    @RequestMapping("/deleteMyNode")
    @ResponseBody
    public int deleteMyNode(@RequestBody NodeAndUser nodeAndUser,
                            HttpServletRequest request){
        System.out.println("删除的笔记："+nodeAndUser);
        //文件删除
        String[] path = {nodeAndUser.getNodename()+".md"};
        String dir = request.getServletContext().getRealPath("/upload/" + nodeAndUser.getUser_id() + "/" + nodeAndUser.getClass_name() + "/" + nodeAndUser.getLanguage() + "/");
        if(delete(path,dir)){
            //数据删除
            nodeService.deleteNodeByNodeId(nodeAndUser);
            return 1;
        }else{
            return 0;
        }

    }

    /**
     * 从tomcat服务器删除文件
     * @param pathArr
     * @param dir
     * @return
     */
    public boolean delete(String[] pathArr,String dir) {
        int len = pathArr.length;
        int count = 0;
        for (String path : pathArr) {
            //拼接文件完整路径
            String abpath = dir+ File.separator + path;
            //获取需要删除的文件
            File deleteFile = new File(abpath);
            if (deleteFile.exists() && deleteFile.isFile() && deleteFile.delete() == true) {
                count++;
            }
        }
        return count==len ? true:false;
    }

    @RequestMapping("/alter")
    @ResponseBody
    public int alterMyNode(@RequestBody NodeAndUser nodeAndUser,
                           HttpServletRequest request){
        NodeAndUser node_origin = nodeService.findNodeByNodeId(nodeAndUser.getNode_id());
        //找到原来的文件得到原来文件的位置
        String oldPath = request.getServletContext().getRealPath("/upload/"+node_origin.getUser_id() + "/" + node_origin.getClass_name() + "/" + node_origin.getLanguage() + "/");
        //找到新的文件路径
        String newPath = request.getServletContext().getRealPath("/upload/"+nodeAndUser.getUser_id() + "/" + nodeAndUser.getClass_name() + "/" + nodeAndUser.getLanguage() + "/");
        //1.复制文件到修改的目录
        //创建文件对象
        File file_old = new File(oldPath +File.separator + node_origin.getNodename()+".md");
        File file = new File(newPath+ File.separator);
        File file_new = new File(newPath + File.separator + nodeAndUser.getNodename()+".md");
        //若保存文件的地址不存在，则创建目录
        if(!file.exists()) {
            file.mkdirs();
        }
        try {
            copyFileUsingStream(file_old,file_new);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //2.删除原来的文件
        deleteMyNode(node_origin,request);
        //修改删除原来的数据
        nodeService.alterNodeByNodeId(nodeAndUser);
        //添加新的数据
        Node node = new Node();
        node.setUser_id(nodeAndUser.getUser_id());
        node.setNodename(nodeAndUser.getNodename());
        node.setLanguage(nodeAndUser.getLanguage());
        node.setClass_name(nodeAndUser.getClass_name());
        node.setNode_id(nodeAndUser.getNode_id());
        node.setPopularity(node_origin.getPopularity());
        node.setTime(node_origin.getTime());
        nodeService.createNode(node);
        return 1;
    }
    //复制文件
    private static void copyFileUsingStream(File source, File dest) throws IOException {
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream(source);
            os = new FileOutputStream(dest);
            System.out.println(is);
            System.out.println(os);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            is.close();
            os.close();
        }
    }
}
